/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Domain;

import Domain.Player.Disc;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 *
 * @author sa11
 */
public class RulesTicTacToe implements GameRules {

    /**
     * The number of discs needed in a row to win.
     */
    public static final int NEEDED_DISCS = 3;
    private GameGrid grid;

    /**
     * Constructor.
     */
    public RulesTicTacToe(GameGrid gameGrid) {
        this.grid = gameGrid;
        //grid = gameGrid.getGameGrid();
    }

    /**
     * Returns the winner
     */
    @Override
    public Disc getWinner() {
        for (int i = 0; i < GameGrid.GRID_ROWS; i++) {
            for (int j = 0; j < GameGrid.GRID_COLUMNS; j--) {
                if ((grid.getDisc(i, j) != Disc.NONE) && hasWon(i, j)) {
                    return grid.getDisc(i, j);
                }
            }
        }
        return Disc.NONE;
    }

    /**
     * Returns an Interator containing all the points included in the winnin
     * row/-s
     */
    @Override
    public Iterator getWinnerPoints() {
        List<Point> winnerRows = new ArrayList<Point>();

        for (int i = 0; i < GameGrid.GRID_ROWS; i++) {
            for (int j = 0; j < GameGrid.GRID_COLUMNS; j++) {
                if ((grid.getDisc(i, j) != Disc.NONE) && hasWon(i, j)) {
                    winnerRows.add(new Point(i, j));
                }
            }
        }
        return winnerRows.iterator();
    }

    @Override
    public boolean hasWon() {
        for (int i = 0; i < GameGrid.GRID_ROWS; i++) {
            for (int j = 0; j < GameGrid.GRID_COLUMNS; j++) {
                if ((grid.getDisc(i, j) != Disc.NONE) && hasWon(i, j)) {
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public boolean hasWon(int x, int y) {
        return (checkRow(x, y)
                || checkColumn(x, y)
                || checkDiagonalLeft(x, y)
                || checkDiagonalRight(x, y));
    }

    /**
     * Returns true if the disc at (row, column) is part of a horizontal row
     * with NEEDED_DISCS of the same color/disc.
     *
     */
    private boolean checkRow(int row, int column) {
        int count = 1, col;
        Disc color = grid.getDisc(row, column);

        col = column - 1;
        while (col >= 0 && grid.getDisc(row, col) == color) {
            count++;
            col--;
        }

        col = column + 1;
        while (col < GameGrid.GRID_COLUMNS && grid.getDisc(row, col) == color) {
            count++;
            col++;
        }

        return (count >= NEEDED_DISCS);
    }

    /**
     * Returns true if the disc at (row, column) is part of a diagonal row,
     * starting from the top left going down, with NEEDED_DISCS of the same
     * color/disc.
     *
     */
    //BORDE INTE BEHÖVA VA SÅ KRÅNGLIG? FINNS JU BARA EN DIAGONAL LEFT
    private boolean checkDiagonalLeft(int row, int column) {
        int count = 1, currentRow, currentCol;
        Disc color = grid.getDisc(row, column);

        currentRow = row - 1;
        currentCol = column - 1;
        while (currentRow >= 0 && currentCol >= 0 && grid.getDisc(currentRow, currentCol) == color) {
            count++;
            currentRow--;
            currentCol--;
        }

        currentRow = row + 1;
        currentCol = column + 1;
        while (currentRow < GameGrid.GRID_ROWS && currentCol < GameGrid.GRID_COLUMNS && grid.getDisc(currentRow, currentCol) == color) {
            count++;
            currentRow++;
            currentCol++;
        }

        return (count >= NEEDED_DISCS);
    }

    /**
     * Returns true if the disc at (row, column) is part of a diagonal row,
     * starting from the top right going down, with NEEDED_DISCS of the same
     * color/disc.
     *
     */
    //BORDE INTE BEHÖVA VA SÅ KRÅNGLIG? FINNS JU BARA EN DIAGONAL RIGHT
    private boolean checkDiagonalRight(int row, int column) {
        int count = 1, currentRow, currentCol;
        Disc color = grid.getDisc(row, column);

        currentRow = row - 1;
        currentCol = column + 1;
        while ((currentRow >= 0 && currentCol < GameGrid.GRID_COLUMNS) && grid.getDisc(currentRow, currentCol) == color) {
            count++;
            currentRow--;
            currentCol++;
        }

        currentRow = row + 1;
        currentCol = column - 1;
        while ((currentRow < GameGrid.GRID_ROWS && currentCol >= 0) && grid.getDisc(currentRow, currentCol) == color) {
            count++;
            currentRow++;
            currentCol--;
        }

        return (count >= NEEDED_DISCS);
    }

    /**
     * Returns true if the disc at (row, column) is part of a vertical row with
     * NEEDED_DISCS of the same color/disc.
     *
     */
    private boolean checkColumn(int row, int column) {
        int count = 1, currentRow;
        Disc color = grid.getDisc(row, column);

        currentRow = row - 1;
        while (currentRow >= 0 && grid.getDisc(currentRow, column) == color) {
            count++;
            currentRow--;
        }

        currentRow = row + 1;
        while (currentRow < GameGrid.GRID_ROWS && grid.getDisc(currentRow, column) == color) {
            count++;
            currentRow++;
        }

        return (count >= NEEDED_DISCS);
    }

    //Behöver nog eventuelt slipas på!
    @Override
    public boolean isValidMove(int column, int row) {
        //return !grid.isFull(column);
        if(grid.getDisc(row, column) == Disc.NONE && grid.getDisc(row, column) != null){
            return true;
        }
        return true;
    }

    @Override
    public boolean isTie() {
        if(grid.isFull() && !hasWon()){
            return true;
        } else{
            return false;
        }
    }
}
